from settings import g_settings,g_logger,PROJECT_NAME
import tornado.web
import tornado.ioloop
import tornado.httpserver
import tornado.options
from tornado.websocket import WebSocketHandler
import random
import platform
import json
import time
from datetime import datetime
import threading
from queue import Queue

g_sendMessageQueue = Queue()
g_websocketSet = set()
g_is_open_send_message_cb = True # 是否首次开启发送ws消息回调


def send_message_callback():

    if not g_sendMessageQueue.empty():
        message = g_sendMessageQueue.get()
        g_sendMessageQueue.task_done()
        # print("send_message_callback()", len(g_websocketSet),message)
        for websocket in g_websocketSet:
            try:
                websocket.write_message(message)
            except Exception as e:
                g_logger.error("send_message_callback() write error:%s"%str(e))
    else:
        time.sleep(0.1)
    # tornado.ioloop.IOLoop.current().add_callback(send_message_callback)

def add_message(message):
    g_sendMessageQueue.put(message)

    if g_sendMessageQueue.qsize() > 50:
        g_sendMessageQueue.get()
        g_sendMessageQueue.task_done()

class WSHandler(WebSocketHandler):
    wd = 0
    init_timestamp = 0
    def open(self):
        self.wd = random.randint(10000,99999)
        self.init_timestamp = int(time.time())
        g_logger.info("open() wd=%d"%self.wd)

        g_websocketSet.add(self)

        global g_is_open_send_message_cb
        if g_is_open_send_message_cb:
            g_is_open_send_message_cb = False
            tornado.ioloop.IOLoop.current().add_callback(send_message_callback)

    def on_message(self, message):
        g_logger.info("on_message() wd=%d,message=%s"%(self.wd,str(message)))

        try:
            message_json = json.loads(message)  # data转换为json格式的message
            message_type = message_json.get("message_type","message_type")
            message_uuid = message_json.get("message_uuid","message_uuid")

            if message_type == "clients": # 查询所有在线client
                data = []

                for websocket in g_websocketSet:
                    data.append({
                        "wd":websocket.wd,
                        "init_timestamp": websocket.init_timestamp
                    })

                ack_data = {
                    "message_type": message_type,
                    "message_uuid": message_uuid,
                    "msg": "ack success",
                    "result": 1000,
                    "data": data
                }
                ack_data_message = json.dumps(ack_data)
                self.write_message(ack_data_message)

            elif message_type == "heart": # 心跳包
                ack_data = {
                    "message_type": message_type,
                    "message_uuid": message_uuid,
                    "msg": "ack success",
                    "result": 1000,
                }
                ack_data_message = json.dumps(ack_data)
                self.write_message(ack_data_message)
            else:
                g_logger.error("unknown message_type:%s"%message_type)

        except Exception as e:
            g_logger.error("on_message() error: %s "%str(e))


    def on_close(self):
        g_logger.info("on_close() wd=%d"%self.wd)
        try:
            g_websocketSet.remove(self)
        except Exception as e:
            g_logger.error("on_close() error: %s "%str(e))

    def check_origin(self, origin):
        g_logger.info("check_origin() wd=%d,origin=%s"%(self.wd,str(origin)))

        return True  # 允许WebSocket的跨域请求

class WSServer():

    def run(self,ip, port, debug=True):
        g_logger.info("WSServer.run() ws://%s:%d" % (ip, port))
        g_logger.info(g_settings.getStr())
        g_logger.info("Start Success")

        # tornado.options.parse_command_line()
        max_buffer_size = 1024 * 1024 * 10  # 文件最大上传字节长度（10M）
        if "Windows" == platform.system() or "windows" == platform.system():
            reuse_port = False  # Windows平台不支持端口复用
            autoreload = False
            num_processes = 1
        else:
            reuse_port = True
            autoreload = False
            num_processes = 0

        app = tornado.web.Application([
                (r"/register", WSHandler),
            ],
            websocket_ping_interval=5, # WebSocket ping探活包发送间隔秒数
            xsrf_cookies=False,
            cookie_secret=PROJECT_NAME,
            autoreload=autoreload, #
            debug=debug
            )

        server = tornado.httpserver.HTTPServer(app, max_buffer_size=max_buffer_size)
        server.bind(port=port, reuse_port=reuse_port)
        server.start(num_processes=num_processes)
        tornado.ioloop.IOLoop.current().start()

if __name__ == '__main__':
    wsServer = WSServer()
    wsServer.run(g_settings.ip, g_settings.port,debug=g_settings.debug)